Auto de-dupe build scripts to link
authorAlex Crichton <alex@alexcrichton.com>
Thu, 8 Oct 2015 06:26:05 +0000 (23:26 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 8 Oct 2015 06:26:05 +0000 (23:26 -0700)
I removed this in 68014ab8 thinking it wasn't necessary, which it technically
isn't for correctness but it ends up leading to absurdly long command lines to
the compiler for larger projects. This also changes the `Vec` to be a `BTreeSet`
to have sorting and deduplication as we go along which should be much faster
than waiting to sort until the very end.

src/cargo/ops/cargo_rustc/custom_build.rs
src/cargo/ops/cargo_rustc/mod.rs
tests/test_cargo_compile_custom_build.rs

index 1232fa9c21ae1a85a38581ef049d42cb7ceee768..83ab98787ada88c9941fa6824c31dd8b277ed816 100644 (file)
@@ -1,4 +1,4 @@
-use std::collections::HashMap;
+use std::collections::{HashMap, BTreeSet};
 use std::fs;
 use std::io::prelude::*;
 use std::path::PathBuf;
@@ -35,8 +35,8 @@ pub struct BuildState {
 
 #[derive(Default)]
 pub struct BuildScripts {
-    pub to_link: Vec<(PackageId, Kind)>,
-    pub plugins: Vec<PackageId>,
+    pub to_link: BTreeSet<(PackageId, Kind)>,
+    pub plugins: BTreeSet<PackageId>,
 }
 
 /// Prepares a `Work` that executes the target as a custom build script.
@@ -354,11 +354,11 @@ pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>,
             return &out[unit]
         }
 
-        let mut to_link = Vec::new();
-        let mut plugins = Vec::new();
+        let mut to_link = BTreeSet::new();
+        let mut plugins = BTreeSet::new();
 
         if !unit.target.is_custom_build() && unit.pkg.has_custom_build() {
-            to_link.push((unit.pkg.package_id().clone(), unit.kind));
+            to_link.insert((unit.pkg.package_id().clone(), unit.kind));
         }
         for unit in cx.dep_targets(unit).iter() {
             let dep_scripts = build(out, cx, unit);
index 5e5655bf8a50d938c80024203b681483b41ca4c4..91892918756878bd8305323fdd044d82bdc18b2c 100644 (file)
@@ -30,7 +30,7 @@ mod job_queue;
 mod layout;
 mod links;
 
-#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
+#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord)]
 pub enum Kind { Host, Target }
 
 #[derive(Default, Clone)]
index 7f35237b93ab39389d50a17ae78d5c93450b731f..3f2788d06248cd255252e8923cc65159dfb068d7 100644 (file)
@@ -1349,3 +1349,65 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
 
 ", compiling = COMPILING, running = RUNNING, fresh = FRESH)));
 });
+
+test!(diamond_passes_args_only_once {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "foo"
+            version = "0.5.0"
+            authors = []
+
+            [dependencies]
+            a = { path = "a" }
+            b = { path = "b" }
+        "#)
+        .file("src/lib.rs", "")
+        .file("tests/foo.rs", "")
+        .file("a/Cargo.toml", r#"
+            [project]
+            name = "a"
+            version = "0.5.0"
+            authors = []
+            [dependencies]
+            b = { path = "../b" }
+            c = { path = "../c" }
+        "#)
+        .file("a/src/lib.rs", "")
+        .file("b/Cargo.toml", r#"
+            [project]
+            name = "b"
+            version = "0.5.0"
+            authors = []
+            [dependencies]
+            c = { path = "../c" }
+        "#)
+        .file("b/src/lib.rs", "")
+        .file("c/Cargo.toml", r#"
+            [project]
+            name = "c"
+            version = "0.5.0"
+            authors = []
+            build = "build.rs"
+        "#)
+        .file("c/build.rs", r#"
+            fn main() {
+                println!("cargo:rustc-link-search=native=test");
+            }
+        "#)
+        .file("c/src/lib.rs", "");
+
+    assert_that(p.cargo_process("build").arg("-v"),
+                execs().with_status(0).with_stdout(&format!("\
+{compiling} c v0.5.0 ([..]
+{running} `rustc [..]`
+{running} `[..]`
+{running} `rustc [..]`
+{compiling} b v0.5.0 ([..]
+{running} `rustc [..]`
+{compiling} a v0.5.0 ([..]
+{running} `rustc [..]`
+{compiling} foo v0.5.0 ([..]
+{running} `[..]rlib -L native=test`
+", compiling = COMPILING, running = RUNNING)));
+});